Ninja 多配置

在 3.17 版中添加。

生成多个 build-<Config>.ninja 文件。

此生成器的功能与 Ninja 生成器非常相似,但有一些关键区别。本文档仅探讨这些区别。

Ninja 生成器不同,Ninja 多配置 同时使用 CMAKE_CONFIGURATION_TYPES 一次生成多配置,而不是仅使用 CMAKE_BUILD_TYPE 生成一个配置。将为每个配置生成一个 build-<Config>.ninja 文件(其中 <Config> 是配置名称)。这些文件应与 ninja -f build-<Config>.ninja 运行。还将使用 CMAKE_DEFAULT_BUILD_TYPE 中的配置或 CMAKE_CONFIGURATION_TYPES 中的第一项生成一个 build.ninja 文件。

cmake --build . --config <Config> 将始终使用 build-<Config>.ninja 进行构建。如果没有指定 --config 参数,cmake --build . 将使用 build.ninja

每个 build-<Config>.ninja 文件都包含 <target> 目标和 <target>:<Config> 目标,其中 <Config>build-<Config>.ninja 中指定的目标相同。此外,如果启用了跨配置模式,build-<Config>.ninja 可能包含 <target>:<OtherConfig> 目标,其中 <OtherConfig> 是跨配置,以及 <target>:all,它在所有跨配置中构建目标。请参阅以下内容了解如何启用跨配置模式。

Ninja Multi-Config 生成器可识别以下变量

CMAKE_CONFIGURATION_TYPES

指定要构建的配置的总集。与其他多配置生成器不同,此变量的默认值为 Debug;Release;RelWithDebInfo

CMAKE_CROSS_CONFIGS

指定从所有 build-<Config>.ninja 文件可获取的配置的 分号分隔列表

CMAKE_DEFAULT_BUILD_TYPE

指定在 build.ninja 文件中默认使用的配置。

CMAKE_DEFAULT_CONFIGS

指定在 build.ninja 中针对目标构建的配置的 分号分隔列表(如果未指定 :<Config> 后缀)。

考虑以下示例

cmake_minimum_required(VERSION 3.16)
project(MultiConfigNinja C)

add_executable(generator generator.c)
add_custom_command(OUTPUT generated.c COMMAND generator generated.c)
add_library(generated ${CMAKE_BINARY_DIR}/generated.c)

现在假设您使用 Ninja Multi-Config 配置项目并运行以下命令之一

ninja -f build-Debug.ninja generated
# OR
cmake --build . --config Debug --target generated

这将构建 generatorDebug 配置,该配置将用于生成 generated.c,而后者将用于构建 generatedDebug 配置。

但是,如果将 CMAKE_CROSS_CONFIGS 设置为 all,您改用运行以下命令

ninja -f build-Release.ninja generated:Debug
# OR
cmake --build . --config Release --target generated:Debug

这将构建 generatorRelease 配置,该配置将用于生成 generated.c,而后者将用于构建 generatedDebug 配置。这对于在构建使用生成代码的编译目标的调试版本的同时运行生成程序的版本优化版本非常有用。

自定义命令

在 3.20 版本中添加。

Ninja 多重配置 生成器通过它的跨配置模式向 add_custom_command()add_custom_target() 中添加额外功能。可以在“命令配置”(正在使用的 build-<Config>.ninja 文件的“本机”配置)或“输出配置”(用于评估 OUTPUTBYPRODUCTS 的配置)上下文中评估 COMMANDDEPENDSWORKING_DIRECTORY 参数。

如果 OUTPUTBYPRODUCTS 命名了一个路径,该路径对于多个配置是通用的(例如,它不使用任何生成器表达式),则默认情况下会在命令配置中评估所有参数。如果所有 OUTPUTBYPRODUCTS 路径对于每个配置都是唯一的(例如,通过使用 $<CONFIG> 生成器表达式),COMMAND 的第一个参数在默认情况下仍然在命令配置中进行评估,而所有后续参数以及 DEPENDSWORKING_DIRECTORY 的参数在输出配置中进行评估。可以使用 $<OUTPUT_CONFIG:...>$<COMMAND_CONFIG:...> 生成器表达式覆盖这些默认设置。请注意,如果 DEPENDS 中以名称指定了某个目标,或者作为 COMMAND 的第一个参数指定了某个目标,则该目标始终在命令配置中进行评估,即使它用 $<OUTPUT_CONFIG:...>(因为它的普通名称不是生成器表达式)进行了包装。

例如,请考虑以下代码

add_custom_command(
  OUTPUT "$<CONFIG>.txt"
  COMMAND
    generator "$<CONFIG>.txt"
              "$<OUTPUT_CONFIG:$<CONFIG>>"
              "$<COMMAND_CONFIG:$<CONFIG>>"
  DEPENDS
    tgt1
    "$<TARGET_FILE:tgt2>"
    "$<OUTPUT_CONFIG:$<TARGET_FILE:tgt3>>"
    "$<COMMAND_CONFIG:$<TARGET_FILE:tgt4>>"
  )

假设 generatortgt1tgt2tgt3tgt4 都是可执行目标,并且假设 $<CONFIG>.txt 是使用 Release 命令配置在 Debug 输出配置中构建的。Release 版本的 generator 目标使用 Debug.txt Debug Release 作为参数进行调用。该命令依赖于 Release 版本的 tgt1tgt4 构建,以及 Debug 版本的 tgt2tgt3 构建。

目标的 PRE_BUILDPRE_LINKPOST_BUILD 自定命令仅在其“本机”配置(build-Release.ninja 文件中的 Release 配置)中运行,除非它们没有 BYPRODUCTS 或其 BYPRODUCTS 在每个配置中都是唯一的。请考虑以下示例

add_executable(exe main.c)
add_custom_command(
  TARGET exe
  POST_BUILD
  COMMAND
    ${CMAKE_COMMAND} -E echo "Running no-byproduct command"
  )
add_custom_command(
  TARGET exe
  POST_BUILD
  COMMAND
    ${CMAKE_COMMAND} -E echo
    "Running separate-byproduct command for $<CONFIG>"
  BYPRODUCTS $<CONFIG>.txt
  )
add_custom_command(
  TARGET exe
  POST_BUILD
  COMMAND
    ${CMAKE_COMMAND} -E echo
    "Running common-byproduct command for $<CONFIG>"
  BYPRODUCTS exe.txt
  )

在此示例中,如果您在 build-Release.ninja 中构建 exe:Debug,则会运行第一个和第二个自定命令,因为它们的副产品在每个配置中都是唯一的,但最后一个自定命令不会运行。但是,如果您在 build-Release.ninja 中构建 exe:Release,则三个自定命令都会运行。